/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package aritmeticacomputacional;

/**
 * @author Charles
 * @author João Paulo
 */
public class Operacoes {

    public static PontoFixoNSinalizado soma(PontoFixoNSinalizado n1, PontoFixoNSinalizado n2) {
        String resultado = "";
        int valor = 0;
        for (int i = 15; i >= 0; i--) {
            valor += Integer.parseInt(n1.getSignificando().charAt(i) + "") + Integer.parseInt(n2.getSignificando().charAt(i) + "");
            if (valor < 2) {
                resultado += valor;
                valor = 0;
            } else {
                resultado += valor % 2;
                valor = 1;
            }
        }
        PontoFixoNSinalizado res = new PontoFixoNSinalizado(new StringBuilder(resultado).reverse());
        if (valor != 0) {
            res.setOverflow(true);
        }
        return res;
    }

    public static PontoFixoNSinalizado sub(PontoFixoNSinalizado n1, PontoFixoNSinalizado n2) {
        String resultado = "";
        int valor = 0;
        for (int i = 15; i >= 0; i--) {
            valor += Integer.parseInt(n1.getSignificando().charAt(i) + "") - Integer.parseInt(n2.getSignificando().charAt(i) + "");
            if (valor >= 0) {
                resultado += valor;
                valor = 0;
            } else {
                for (int j = i; j >= 0; j--) {
                    if (n1.getSignificando().charAt(j) == '0') {
                        n1.getSignificando().setCharAt(j, '1');
                    } else {
                        n1.getSignificando().setCharAt(j, '0');
                        break;
                    }
                }
                valor = 1;
                i++;
            }
        }
//        StringBuilder sb = new StringBuilder(resultado);
//        return new PontoFixoNSinalizado(new StringBuilder(sb.reverse().toString()));
        return new PontoFixoNSinalizado(new StringBuilder(resultado).reverse());
    }

    public static PontoFixoNSinalizado mult(PontoFixoNSinalizado n1, PontoFixoNSinalizado n2) {
        String aux = "";
        PontoFixoNSinalizado resultado = new PontoFixoNSinalizado(new StringBuilder("0000000000000000"));
        PontoFixoNSinalizado pfns;
        for (int i = 15; i >= 0; i--) {
            if (n2.getSignificando().charAt(i) != '0') {
                pfns = new PontoFixoNSinalizado(new StringBuilder(n1.getSignificando().toString() + aux));
                resultado = Operacoes.soma(resultado, pfns);
            }
            aux += 0;
        }
        return resultado;
    }

    public static PontoFixoSinalizado mult(PontoFixoSinalizado n1, PontoFixoSinalizado n2) {
        String aux = "";
        PontoFixoNSinalizado resultado = new PontoFixoNSinalizado(new StringBuilder("0000000000000000"));
        PontoFixoNSinalizado pfs;

        int ok = 0;

        PontoFixoNSinalizado q = new PontoFixoNSinalizado(n1.getComplementoDois());

        if (n1.getComplementoDois().charAt(1) == '1') {
            n1.complementoUm();
            q = new PontoFixoNSinalizado(n1.getComplementoDois());
            ok++;
        }

        PontoFixoNSinalizado m = new PontoFixoNSinalizado(n2.getComplementoDois());

        if (n2.getComplementoDois().charAt(0) == '1') {
            n2.complementoUm();
            m = new PontoFixoNSinalizado(n2.getComplementoDois());
            ok++;
        }

        for (int i = 15; i >= 0; i--) {
            if (m.getSignificando().charAt(i) != '0') {
                pfs = new PontoFixoNSinalizado(new StringBuilder(q.getSignificando().toString() + aux));
                resultado = Operacoes.soma(resultado, pfs);
            }
            aux += 0;
        }

        PontoFixoSinalizado res = new PontoFixoSinalizado(resultado.getSignificando());
        if (ok % 2 == 1) {
            res.complementoDois();
        }
        return res;
    }

    public static PontoFixoNSinalizado div(PontoFixoNSinalizado q, PontoFixoNSinalizado m) {

        String q0 = "0";
        //       boolean bit = true;
        int n = 16;

//        PontoFixoNSinalizado q = new PontoFixoNSinalizado(new StringBuilder("0000000000100001"));
//        PontoFixoNSinalizado m = new PontoFixoNSinalizado(new StringBuilder("0000000000000011"));
        PontoFixoNSinalizado a = new PontoFixoNSinalizado(new StringBuilder("0000000000000000"));

        do {
            a = new PontoFixoNSinalizado(new StringBuilder(a.getSignificando() + q.getSignificando().substring(0, 1)));
            q = new PontoFixoNSinalizado(new StringBuilder(q.getSignificando() + q0));

            a = Operacoes.sub(a, m);

            if (a.getSignificando().charAt(0) == '1') {
                q0 = "0";
                a = Operacoes.soma(a, m);
            } else {
                q0 = "1";
            }

            n--;
        } while (n >= 0);

        System.out.println(q.getSignificando());

        return new PontoFixoNSinalizado(new StringBuilder(q.getSignificando()));
    }

    public static PontoFixoSinalizado div(PontoFixoSinalizado qa, PontoFixoSinalizado ma) {

        int ok = 0;

        PontoFixoNSinalizado q = new PontoFixoNSinalizado(qa.getComplementoDois());

        if (qa.getComplementoDois().charAt(1) == '1') {
            qa.complementoUm();
            q = new PontoFixoNSinalizado(qa.getComplementoDois());
            ok++;
        }

        PontoFixoNSinalizado m = new PontoFixoNSinalizado(ma.getComplementoDois());

        if (ma.getComplementoDois().charAt(0) == '1') {
            ma.complementoUm();
            m = new PontoFixoNSinalizado(ma.getComplementoDois());
            ok++;
        }

        String q0 = "0";
        //       boolean bit = true;
        int n = 16;

//        PontoFixoNSinalizado q = new PontoFixoNSinalizado(new StringBuilder("0000000000100001"));
//        PontoFixoNSinalizado m = new PontoFixoNSinalizado(new StringBuilder("0000000000000011"));
        PontoFixoNSinalizado a = new PontoFixoNSinalizado(new StringBuilder("0000000000000000"));

        do {
            a = new PontoFixoNSinalizado(new StringBuilder(a.getSignificando() + q.getSignificando().substring(0, 1)));
            q = new PontoFixoNSinalizado(new StringBuilder(q.getSignificando() + q0));

            a = Operacoes.sub(a, m);

            if (a.getSignificando().charAt(0) == '1') {
                q0 = "0";
                a = Operacoes.soma(a, m);
            } else {
                q0 = "1";
            }

            n--;
        } while (n >= 0);

        System.out.println(q.getSignificando());

        PontoFixoSinalizado resposta = new PontoFixoSinalizado(q.getSignificando());

        if (ok % 2 == 1) {
            resposta.complementoDois();
        }

        return resposta;
    }

    public static boolean isLowerorEqual(String dividendo, String divisor) {
        for (int i = 0; i < 16; i++) {
            if (dividendo.charAt(i) == '0' && divisor.charAt(i) == '1') {
                return true;
            } else if (dividendo.charAt(i) == '1' && divisor.charAt(i) == '0') {
                return false;
            }
        }

        return true;
    }

    public static String preenche(String str) {
        String resultado = str;
        while (resultado.length() < 16) {
            resultado = "0" + resultado;
        }
        return resultado;

    }

    public static String getValue(String parcial) {
        if (parcial.contains("1")) {
            return parcial.substring(parcial.indexOf("1"));
        } else {
            return "0";
        }
    }

    public static PontoFixoSinalizado soma(PontoFixoSinalizado n1, PontoFixoSinalizado n2) {
        String resultado = "";
        int valor = 0;
        for (int i = 15; i >= 0; i--) {
            valor += Integer.parseInt(n1.getComplementoDois().charAt(i) + "") + Integer.parseInt(n2.getComplementoDois().charAt(i) + "");
            if (valor < 2) {
                resultado += valor;
                valor = 0;
            } else {
                resultado += valor % 2;
                valor = 1;
            }
        }
//        StringBuffer sb = new StringBuffer(resultado);
        return new PontoFixoSinalizado(new StringBuilder(resultado).reverse());
//        return new PontoFixoNSinalizado(new StringBuilder(sb.reverse().toString()));
    }

    public static PontoFixoSinalizado sub(PontoFixoSinalizado n1, PontoFixoSinalizado n2) {
        String resultado = "";
//        n2.complementoDois();
        int valor = 0;
        for (int i = 15; i >= 0; i--) {
            valor += Integer.parseInt(n1.getComplementoDois().charAt(i) + "") + Integer.parseInt(n2.getComplementoDois().charAt(i) + "");
            if (valor < 2) {
                resultado += valor;
                valor = 0;
            } else {
                resultado += valor % 2;
                valor = 1;
            }
        }
//        StringBuffer sb = new StringBuffer(resultado);
        return new PontoFixoSinalizado(new StringBuilder(resultado).reverse());
//        return new PontoFixoNSinalizado(new StringBuilder(sb.reverse().toString()));
    }

    public static PontoFlutuante soma(PontoFlutuante n1, PontoFlutuante n2) {
        PontoFlutuante resp = new PontoFlutuante(new StringBuilder(Operacoes.soma(new PontoFixoNSinalizado(new StringBuilder(n1.getSignificando().toString())), new PontoFixoNSinalizado(new StringBuilder(n2.getSignificando().toString()))).toString()));
        Operacoes.soma(new PontoFixoNSinalizado(new StringBuilder(n1.getSignificando().toString())), new PontoFixoNSinalizado(new StringBuilder(n2.getSignificando().toString())));

        return resp;
    }
}
